package com.bolt.report.engine.export;

import com.bolt.common.convert.Convert;
import com.bolt.report.engine.ExporterInput;
import com.bolt.report.engine.ExporterOutput;
import com.bolt.report.engine.ReportConstants;
import com.bolt.report.engine.model.Column;
import com.bolt.report.engine.model.PageDetails;
import com.bolt.report.engine.model.ReportPrint;
import com.bolt.report.exception.ReportException;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public abstract class AbstractExporter<O extends ExporterOutput> implements Exporter<ExporterInput, O> {

    protected ExporterInput exporterInput;

    protected O exporterOutput;

    protected ReportPrint reportPrint;

    protected Map<String, Object> parameters;

    public AbstractExporter() {
        this.parameters = new HashMap<>();
    }

    public AbstractExporter(Map<String, Object> parameters) {
        this.parameters = parameters;
    }

    protected void initInput() {
        reportPrint = exporterInput.getReportPrint();
    }

    public O getExporterOutput() {
        return exporterOutput;
    }

    @Override
    public void setExporterInput(ExporterInput input) {
        this.exporterInput = input;
    }

    @Override
    public void setExporterOutput(O output) {
        exporterOutput = output;
    }

    @Override
    public void setParameter(String name, Object value) {
        parameters.put(name, value);
    }

    @Override
    public Object getParameter(String name) {
        return parameters.get(name);
    }




    protected int getTableWidth(PageDetails page) {
        List<Column> columns = page.getColumn();
        return columns.stream().mapToInt(k -> k.getWidth()).sum();
    }

    protected PageRange getPageRange() {
        Integer startPageIndex = null;
        Integer endPageIndex = null;

        int lastPageIndex = -1;
        if (reportPrint.getPages() != null) {
            lastPageIndex = reportPrint.getPages().size() - 1;
        }

        Integer start = Convert.toInt(parameters.get(ReportConstants.START_PAGE_INDEX), 0);
        if (start != null) {
            startPageIndex = start;
            if (startPageIndex < 0 || startPageIndex > lastPageIndex) {
                throw new ReportException("export.common.page.index.out.of.pageSize {}:{}",
                        new Object[]{startPageIndex, lastPageIndex}
                );
            }
        }

        Integer end = Convert.toInt(parameters.get(ReportConstants.END_PAGE_INDEX), lastPageIndex);
        if (end != null) {
            endPageIndex = end;
            int startPage = startPageIndex == null ? 0 : startPageIndex;
            if (endPageIndex < startPage || endPageIndex > lastPageIndex) {
                throw new ReportException("export.common.page.index.out.of.pageSize {}:{}",
                        new Object[]{startPageIndex, lastPageIndex}
                );
            }
        }


        Integer pageIndex = Convert.toInt(parameters.get(ReportConstants.PAGE_INDEX), null);
        if (pageIndex != null) {
            if (pageIndex < 0 || pageIndex > lastPageIndex) {
                throw new ReportException("export.common.page.index.out.of.pageSize {}:{}",
                        new Object[]{pageIndex, lastPageIndex}
                );
            }
            startPageIndex = pageIndex;
            endPageIndex = pageIndex;
        }

        PageRange pageRange = null;

        if (startPageIndex != null || endPageIndex != null) {
            pageRange = new PageRange(startPageIndex, endPageIndex);
        }

        return pageRange;
    }

    protected class PageRange {
        private Integer startPageIndex;
        private Integer endPageIndex;

        public PageRange(Integer startPageIndex, Integer endPageIndex) {
            this.startPageIndex = startPageIndex;
            this.endPageIndex = endPageIndex;
        }


        public Integer getStartPageIndex() {
            return startPageIndex;
        }

        public Integer getEndPageIndex() {
            return endPageIndex;
        }
    }


}